1
|
|
|
const app = angular.module('rv2Flash', []); |
2
|
|
|
|
3
|
|
|
app.run([ |
4
|
|
|
'$rootScope', function($rootScope) { |
5
|
|
|
return $rootScope.flashes = []; |
6
|
|
|
} |
7
|
|
|
]); |
8
|
|
|
|
9
|
|
|
app.directive('dynamic', [ |
10
|
|
|
'$compile', function($compile) { |
11
|
|
|
return { |
12
|
|
|
restrict: 'A', |
13
|
|
|
replace: true, |
14
|
|
|
link: function(scope, ele, attrs) { |
15
|
|
|
return scope.$watch(attrs.dynamic, function(html) { |
16
|
|
|
ele.html(html); |
17
|
|
|
return $compile(ele.contents())(scope); |
18
|
|
|
}); |
19
|
|
|
} |
20
|
|
|
}; |
21
|
|
|
} |
22
|
|
|
]); |
23
|
|
|
|
24
|
|
|
app.directive('applytransclude', [ |
25
|
|
|
'$compile', function($compile) { |
|
|
|
|
26
|
|
|
return { |
27
|
|
|
restrict: 'A', |
28
|
|
|
link: function(scope, ele, attrs) { |
|
|
|
|
29
|
|
|
scope._transclude(scope, function(clone, scope) { |
|
|
|
|
30
|
|
|
ele.empty().append(clone); |
31
|
|
|
}); |
32
|
|
|
} |
33
|
|
|
}; |
34
|
|
|
} |
35
|
|
|
]); |
36
|
|
|
|
37
|
|
|
app.directive('closeFlash', [ |
38
|
|
|
'$compile', '$rootScope', 'Flash', function($compile, $rootScope, Flash) { |
39
|
|
|
return { |
40
|
|
|
link: function(scope, ele, attrs) { |
41
|
|
|
return ele.on('click', function() { |
42
|
|
|
let id = parseInt(attrs.closeFlash, 10); |
43
|
|
|
Flash.dismiss(id); |
44
|
|
|
$rootScope.$apply(); |
45
|
|
|
}); |
46
|
|
|
} |
47
|
|
|
}; |
48
|
|
|
} |
49
|
|
|
]); |
50
|
|
|
|
51
|
|
|
app.directive('flashMessage', [ |
52
|
|
|
'Flash', function(Flash) { |
53
|
|
|
return { |
54
|
|
|
restrict: 'E', |
55
|
|
|
scope: { |
56
|
|
|
duration: '=', |
57
|
|
|
showClose: '=', |
58
|
|
|
onDismiss: '&', |
59
|
|
|
name: '@' |
60
|
|
|
}, |
61
|
|
|
link: function(scope, ele, attrs, ctrl, transclude) { |
62
|
|
|
Flash.setTimeout(scope.duration); |
63
|
|
|
Flash.setShowClose(scope.showClose); |
64
|
|
|
function onDismiss(flash) { |
65
|
|
|
if (typeof scope.onDismiss !== 'function') return; |
|
|
|
|
66
|
|
|
scope.onDismiss({flash: flash}); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
Flash.setOnDismiss(onDismiss); |
70
|
|
|
|
71
|
|
|
if (Flash.config.templateTransclude) { |
72
|
|
|
scope._transclude = transclude; |
73
|
|
|
} |
74
|
|
|
}, |
75
|
|
|
transclude: Flash.config.templateTransclude, |
76
|
|
|
template: ` |
77
|
|
|
<div ng-repeat="flash in $root.flashes track by $index" ng-if="flash.config.container === name" class="alert-container"> |
78
|
|
|
` + Flash.config.template + ` |
79
|
|
|
</div> |
80
|
|
|
` |
81
|
|
|
}; |
82
|
|
|
} |
83
|
|
|
]); |
84
|
|
|
|
85
|
|
|
app.provider('Flash', function() { |
86
|
|
|
let defaultConfig = {}; |
87
|
|
|
let templatePresets = { |
88
|
|
|
bootstrap: { |
89
|
|
|
html: ` |
90
|
|
|
<div role="alert" id="{{flash.config.id}}" |
91
|
|
|
class="alert {{flash.config.class}} alert-{{flash.type}} alert-dismissible alertIn alertOut"> |
92
|
|
|
<div type="button" class="close" ng-show="flash.showClose" close-flash="{{flash.id}}"> |
93
|
|
|
<span aria-hidden="true">×</span> |
94
|
|
|
<span class="sr-only">Close</span> |
95
|
|
|
</div> |
96
|
|
|
<span dynamic="flash.text"></span> |
97
|
|
|
</div>`, |
98
|
|
|
transclude: false |
99
|
|
|
}, |
100
|
|
|
transclude: { |
101
|
|
|
html: `<div applytransclude></div>`, |
102
|
|
|
transclude: true |
103
|
|
|
} |
104
|
|
|
}; |
105
|
|
|
|
106
|
|
|
this.setTimeout = function(timeout) { |
107
|
|
|
if (typeof timeout !== 'number') return; |
|
|
|
|
108
|
|
|
defaultConfig.timeout = timeout; |
109
|
|
|
}; |
110
|
|
|
this.setShowClose = function(value) { |
111
|
|
|
if (typeof value !== 'boolean') return; |
|
|
|
|
112
|
|
|
defaultConfig.showClose = value; |
113
|
|
|
}; |
114
|
|
|
this.setTemplate = function(template) { |
115
|
|
|
if (typeof template !== 'string') return; |
|
|
|
|
116
|
|
|
defaultConfig.template = template; |
117
|
|
|
}; |
118
|
|
|
this.setTemplatePreset = function(preset) { |
119
|
|
|
if (typeof preset !== 'string' |
120
|
|
|
|| !(preset in templatePresets)) return; |
|
|
|
|
121
|
|
|
|
122
|
|
|
let template = templatePresets[preset]; |
123
|
|
|
this.setTemplate(template.html); |
124
|
|
|
defaultConfig.templateTransclude = template.transclude; |
125
|
|
|
}; |
126
|
|
|
this.setOnDismiss = function(callback) { |
127
|
|
|
if (typeof callback !== 'function') return; |
|
|
|
|
128
|
|
|
defaultConfig.onDismiss = callback; |
129
|
|
|
}; |
130
|
|
|
|
131
|
|
|
this.setAutoDismiss = function (dismiss) { |
132
|
|
|
if (typeof dismiss !== 'boolean') return; |
|
|
|
|
133
|
|
|
defaultConfig.autoDismiss = dismiss; |
134
|
|
|
}; |
135
|
|
|
|
136
|
|
|
this.setTimeout(5000); |
137
|
|
|
this.setShowClose(true); |
138
|
|
|
this.setTemplatePreset('bootstrap'); |
139
|
|
|
this.setAutoDismiss(false); |
140
|
|
|
|
141
|
|
|
this.$get = ['$rootScope', '$interval', function($rootScope, $interval) { |
142
|
|
|
const dataFactory = {}; |
143
|
|
|
let counter = 0; |
144
|
|
|
|
145
|
|
|
dataFactory.setTimeout = this.setTimeout; |
146
|
|
|
dataFactory.setShowClose = this.setShowClose; |
147
|
|
|
dataFactory.setOnDismiss = this.setOnDismiss; |
148
|
|
|
dataFactory.config = defaultConfig; |
149
|
|
|
|
150
|
|
|
dataFactory.create = function(type, text, timeout, config, showClose) { |
151
|
|
|
if ($rootScope.flashes.length === 1 && defaultConfig.autoDismiss) { |
152
|
|
|
dataFactory.dismiss($rootScope.flashes[0].id); |
153
|
|
|
} |
154
|
|
|
if (!text) return false; |
|
|
|
|
155
|
|
|
let $this, flash; |
156
|
|
|
$this = this; |
157
|
|
|
flash = { |
158
|
|
|
type: type, |
159
|
|
|
text: text, |
160
|
|
|
config: config, |
161
|
|
|
id: counter++ |
162
|
|
|
}; |
163
|
|
|
flash.showClose = |
164
|
|
|
typeof showClose !== 'undefined' ? |
165
|
|
|
showClose : defaultConfig.showClose; |
166
|
|
|
if (defaultConfig.timeout && typeof timeout === 'undefined') { |
167
|
|
|
flash.timeout = defaultConfig.timeout; |
168
|
|
|
} |
169
|
|
|
else if (timeout) { |
170
|
|
|
flash.timeout = timeout; |
171
|
|
|
} |
172
|
|
|
$rootScope.flashes.push(flash); |
173
|
|
|
if (flash.timeout) { |
174
|
|
|
flash.timeoutObj = $interval(function() { |
175
|
|
|
$this.dismiss(flash.id); |
176
|
|
|
}, flash.timeout, 1); |
177
|
|
|
} |
178
|
|
|
return flash.id; |
179
|
|
|
}; |
180
|
|
|
dataFactory.pause = function(index) { |
181
|
|
|
if ($rootScope.flashes[index].timeoutObj) { |
182
|
|
|
$interval.cancel($rootScope.flashes[index].timeoutObj); |
183
|
|
|
} |
184
|
|
|
}; |
185
|
|
|
dataFactory.dismiss = function(id) { |
186
|
|
|
const index = findIndexById(id); |
187
|
|
|
if (index !== -1) { |
188
|
|
|
const flash = $rootScope.flashes[index]; |
189
|
|
|
dataFactory.pause(index); |
190
|
|
|
$rootScope.flashes.splice(index, 1); |
191
|
|
|
if (typeof defaultConfig.onDismiss === 'function') { |
192
|
|
|
defaultConfig.onDismiss(flash); |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
}; |
196
|
|
|
dataFactory.clear = function() { |
197
|
|
|
while ($rootScope.flashes.length > 0) { |
198
|
|
|
dataFactory.dismiss($rootScope.flashes[0].id); |
199
|
|
|
} |
200
|
|
|
}; |
201
|
|
|
dataFactory.reset = dataFactory.clear; |
202
|
|
|
function findIndexById(id) { |
203
|
|
|
return $rootScope.flashes.map((flash) => flash.id).indexOf(id); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
return dataFactory; |
207
|
|
|
}]; |
208
|
|
|
}); |
209
|
|
|
|
This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.